package com.haiyou.mini.programs.coupon.merchant.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import com.haiyou.common.exception.BusinessException;
import com.haiyou.common.util.IdWorker;
import com.haiyou.mini.programs.config.WxMiniConfig;
import com.haiyou.mini.programs.coupon.merchant.MerchantCouponService;
import com.haiyou.mini.programs.v3.HMACSHA256Util;
import com.haiyou.mini.programs.v3.V3Util;
import com.haiyou.mini.programs.v3.WxConstant;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

import java.util.Map;
import java.util.UUID;

/**
 * 商家劵实现
 * https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/busifavor.shtml
 */
@Slf4j
@RequiredArgsConstructor
public class MerchantCouponServiceImpl implements MerchantCouponService {

    private final WxMiniConfig wxPayConfig;

    @Override
    public String addCoupon(String json) {
        JSONObject jsonObject = request(WxConstant.ADD_STOCKS_URL, json);
        if (jsonObject == null || !jsonObject.containsKey("stock_id")) {
            log.error("创建卡劵失败：{}", jsonObject);
            throw new BusinessException("创建卡劵失败");
        }
        return jsonObject.getString("stock_id");
    }

    @Override
    public void useCoupon(String json) {
        JSONObject jsonObject = request(WxConstant.COUPONS_USE_URL, json);
        if (jsonObject == null || !jsonObject.containsKey("wechatpay_use_time")) {
            log.error("核销卡劵失败：{}", jsonObject);
            throw new BusinessException("核销卡劵失败");
        }
    }

    @Override
    public void diyCouponCode(String stockId, String json) {
        String url = String.format(WxConstant.COUPON_CODES_URL, stockId);
        JSONObject jsonObject = request(url, json);
        if (jsonObject == null || !jsonObject.containsKey("success_codes")) {
            log.error("上传预存code失败：{}", jsonObject);
            throw new BusinessException("上传预存code失败");
        }
    }

    private JSONObject request(String url, String json) {
        try {
            //时间戳
            String timestamp = Long.toString(System.currentTimeMillis() / 1000);
            //随机数
            String nonce_str = UUID.randomUUID().toString();

            //接口URL
            CloseableHttpClient httpclient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(WxConstant.SERVICE_URL + url);

            StringBuffer sb = new StringBuffer();
            sb.append("POST").append("\n");
            sb.append(url).append("\n");
            sb.append(timestamp).append("\n");
            sb.append(nonce_str).append("\n");
            sb.append(json).append("\n");
            log.info("签名原串：{}", sb.toString());

            //计算签名
            String sign = new String(Base64.encodeBase64(V3Util.signRSA(sb.toString(), V3Util.privateKey(wxPayConfig.getRsaPrivateKeyFile(), true))));
            log.info("签名sign值：{}", sign);

            //拼装http头的Authorization内容
            String authorization = "WECHATPAY2-SHA256-RSA2048 mchid=\"" + wxPayConfig.getMchID() + "\",nonce_str=\"" + nonce_str + "\",signature=\"" + sign + "\",timestamp=\"" + timestamp + "\",serial_no=\"" + wxPayConfig.getSerialNo() + "\"";
            log.info("authorization值：{}", authorization);

            //设置头部
            httpPost.setHeader("Content-type", "application/json");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Authorization", authorization);

            httpPost.setEntity(new StringEntity(json, "UTF-8"));
            //获取返回内容
            CloseableHttpResponse response = httpclient.execute(httpPost);
            HttpEntity httpEntity = response.getEntity();
            String resContent = new String(V3Util.InputStream2Byte(httpEntity.getContent()));
            log.info("返回内容：{}", resContent);
            JSONObject jsonObject = JSON.parseObject(resContent);

            EntityUtils.consume(httpEntity);
            response.close();

            return jsonObject;
        } catch (Exception e) {
            log.error("发送POST请求异常！{},{}", e.getMessage(), e);
        }
        throw new BusinessException("请求异常");
    }

    /**
     * https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/marketing/miniprogram/chapter3_1.shtml
     * 签名参数：
     * out_request_no0=abc123&send_coupon_merchant=10016226&stock_id0=1234567&key=xxxxx
     *
     * @param stockId
     * @return
     */
    @Override
    public Map<String, String> sendCoupon(String stockId) {
        Map<String, String> params = Maps.newHashMap();
        params.put("mchid", wxPayConfig.getMchID());
        params.put("stock_id", stockId);
        params.put("out_request_no", IdWorker.getId());

        StringBuilder key = new StringBuilder();
        key.append("out_request_no0=").append(params.get("out_request_no")).append("&");
        key.append("send_coupon_merchant=").append(params.get("mchid")).append("&");
        key.append("stock_id0=").append(params.get("stock_id")).append("&");
        key.append("key=").append(wxPayConfig.getKey());
        log.info("---->签名参数：{}", key);
        params.put("sign", HMACSHA256Util.sha256_HMAC(key.toString(), wxPayConfig.getKey()));
        log.info("---->发劵返回参数：{}", params);
        return params;
    }
}
